package Runde5;

public class List<A> {
		
		
		private ListElement start;
		private ListElement end;
		
		/**
		 * @postcondition Creates a new List
		 */
		public List() {
			this.start = new ListElement(null);
			this.end = new ListElement(null);
			start.next = end;
			end.prev = start;
		}
		
		/**
		 * @precondition <A> != null
		 * @postcondition Adds a new <A> to the List
		 */
		public void add(A valToAdd){
			if (valToAdd == null) {
				return;
			}
			ListElement liEl = new ListElement(valToAdd);
			if (start.next == end){
				end.prev = liEl;
				start.next = liEl;
				liEl.prev = start;
				liEl.next = end;
				
			} else {
				liEl.prev = end.prev;
				liEl.next = end;
				end.prev.next = liEl;
				end.prev = liEl;
			}
		}
		
		/**
		 * @postcondition Returns a new Iterator on the list
		 */
		public Iter<A> iterator() {
			return new Iterator();
		}
		
		/**
		 * @postcondition delivers a readable form of this instance of list
		 */
		public String toString() {
			String output = "";
			ListElement current = start.next;
			while (current.next.content != null) {
				output += current.content + ", ";
				current = current.next;
			}
			return output + current.content;
		}
		
		/**
		 * @postcondition delivers a readable form of this instance of list
		 */
		protected class ListElement {
			private final A content;
			private ListElement prev;
			private ListElement next;
			public ListElement(A content){
				prev = null;
				next = null;
				this.content = content;
			}
		}

		//Iterator-Class (Iter<A>)
		protected class Iterator implements Iter<A> {
				
			ListElement current;	
			
			/**
			 * @postcondition create's a new iterator
			 */
			public Iterator() {
				current = start;
			}
			
			/**
			 * @postcondition returns true if next() != null
			 */
			public boolean hasNext() {
				if (current.next == end || current == end) {
					return false;
				}
				return true;
			}
	
			/**
			 * @postcondition returns true if previous() != null
			 */
			public boolean hasPrevious() {
				if (current.prev == start || current == start) {
					return false;
				}
				return true;
			}
	
			/**
			 * @postcondition places iterator on next element in list and returns it
			 */
			public A next() {
				if (!hasNext() && current == end) {
					return null;
				} 
				current = current.next;
				return current.content;
			}
	
			/**
			 * @postcondition places iterator on previous element in list and returns it
			 */
			public A previous() {
				if (!hasPrevious() && current == start) {
					return null;
				} 
				current = current.prev;
				return current.content;
			}
			
		}

}
